package com.wang.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wang.common.security.exception.ServiceException;
import com.wang.common.security.service.TokenService;
import com.wang.common.core.constants.HttpConstants;
import com.wang.common.core.domain.LoginUser;
import com.wang.common.core.domain.R;
import com.wang.common.core.enums.ResultCode;
import com.wang.common.core.enums.UserIdentity;
import com.wang.system.domain.sysuser.dto.LoginDTO;
import com.wang.system.domain.sysuser.SysUser;
import com.wang.system.domain.sysuser.dto.SysUserAddDTO;
import com.wang.system.domain.sysuser.vo.LoginUserVO;
import com.wang.system.mapper.SysUserMapper;
import com.wang.system.service.ISysUserService;
import com.wang.system.utils.BCryptUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SysUserServiceImpl implements ISysUserService {

    @Autowired
    private SysUserMapper mapper;

    @Autowired
    private TokenService tokenService;

    @Value("${jwt.secret}")
    private String secret;//JWT中签名要使用到的密钥

    /**
     * 登录功能实现
     * @param loginDTO 登录参数 (账号密码)
     * @return
     */
    @Override
    public R<String> login(LoginDTO loginDTO) {

        //1.先从参数中把用户名和密码拿出来
        String userAccount = loginDTO.getUserAccount();
        String password = loginDTO.getPassword();

        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>(); //使用当前对象代替sql语句

        //select password,user_id,nick_name from tb_sys_user where user_account = #{userAccount}
        //2.根据用户名从库中查出当前用户的数据
        SysUser sysUser = mapper.selectOne(wrapper.select(SysUser::getPassword,SysUser::getUserId,SysUser::getNickName)
                .eq(SysUser::getUserAccount, userAccount));

        // -- 如果查询结果为空,说明账号不存在
        if (sysUser == null){
            return R.fail(ResultCode.FAILED_USER_NOT_EXISTS);
        }

        // -- 如果查询结果不为空,说明账号存在

        //3.判断密码是否正确
        //密码正确
        if (BCryptUtil.matchesPassword(password,sysUser.getPassword())){
            //登录成功,返回token
            return R.success(tokenService.createToken(
                            sysUser.getUserId(),
                            UserIdentity.ADMIN.getValue(),
                            sysUser.getNickName(),
                            null,
                            secret));
        }
        //登录失败,返回失败原因
        return R.fail(ResultCode.FAILED_LOGIN);
    }

    @Override
    public int add(SysUserAddDTO sysUserAddDTO) {
        //首先判断数据库中是否存在当前用户
        //根据用户名查询
        //select * from sys_user where user_account = #{user_account}
        List<SysUser> sysUsers = mapper.selectList(
                new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserAccount, sysUserAddDTO.getUserAccount()));

        //如果查询结果为空 --> 说明同名用户已存在,无法新增
        if (!sysUsers.isEmpty()){
            throw new ServiceException(ResultCode.FAILED_USER_EXISTS);
        }

        //走到这里 说明查询结果不为空

        //进行数据的插入
        SysUser sysUser = new SysUser();
        sysUser.setUserAccount(sysUserAddDTO.getUserAccount());
        sysUser.setPassword(BCryptUtil.encryptPassword(sysUserAddDTO.getPassword()));
        sysUser.setNickName(sysUserAddDTO.getNickName());

        return mapper.insert(sysUser);
    }

    @Override
    public R<LoginUserVO> querySysUserInfo(String token) {
        //1.检查token
        //检查token是否为空 + 检查token是否以前缀Bearer开头
        //如果token不为空 且 token以Bearer开头 --> 移除 token 的前缀
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }

        //2.从Redis中获取当前用户的信息
        LoginUser loginUser = tokenService.getLoginUser(token, secret);

        if (loginUser == null){
            //如果为空-->说明 登录状态已过期导致缓存中的用户信息被删除
            //或 用户已经退出登录
            //或 当前用户就没有登录过(只要登录了信息就会存在缓存中)
            //返回失败
            return R.fail();
        }

        //3.设置VO对象的值
        LoginUserVO loginUserVO = new LoginUserVO();
        loginUserVO.setNickName(loginUser.getNickName());

        return R.success(loginUserVO);
    }

    @Override
    public boolean logout(String token) {
        //1.检查token
        //检查token是否为空 + 检查token是否以前缀Bearer开头
        //如果token不为空 且 token以Bearer开头 --> 移除 token 的前缀
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }

        //2.从Redis中删除当前用户信息
        return tokenService.deleteLoginUser(token, secret);
    }
}
